import {instantiate, Node, NodePool, Prefab} from "cc";

// 节点对象池
/**
 * 一个节点一个对象池，避免对象池拿到节点还要判断是哪一个节点
 * 节点回收与拿取，只会调用 onEnable, onDisable
 */
export class NodePoolManager {
    private _nodePools: Record<string, NodePool> = {};

    private static _instance: NodePoolManager;

    static get instance() {
        if (!this._instance) {
            this._instance = new NodePoolManager;
        }
        return this._instance;
    }

    // 把节点添加到对象池
    put(obj: Node) {
        if (!obj) {
            return;
        }
        const key = obj.name;
        let pool = this._nodePools[key];
        if (!pool) {
            // 如果对象池不存在，那就实例化一个对象池，然后把对象池存起来
            pool = new NodePool();
            this._nodePools[key] = pool;
        } else {
            // 如果对象池存在，那就把节点put到对象池
            pool.put(obj);
        }
    }

    // 通过prefab从对象池拿节点
    get(pf: Prefab) {
        if (!pf) {
            return;
        }
        const key = pf.name;
        let pool = this._nodePools[key];
        let target: Node = null;
        if (!pool) { //节点池是否存在
            // 节点对象池不存在，创建其节点，然后创建其对象池，然后此对象池存储到this._nodePools
            target = instantiate(pf);
            pool = new NodePool();
            this._nodePools[key] = pool;
        } else {
            // 节点对象池存在
            if (pool.size() > 0) { //是否有可用节点
                // 从对象池拿到节点
                target = pool.get();
            } else {
                // 实例化一个节点
                target = instantiate(pf);
            }
        }
        return target;
    }
}